package org.stormphoenix.bbsfamily.filter

import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.beans.factory.annotation.Value
import org.springframework.security.authentication.AuthenticationManager
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
import org.springframework.security.core.context.SecurityContextHolder
import org.springframework.security.core.userdetails.UserDetailsService
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter
import org.stormphoenix.bbsfamily.utils.JwtTokenUtil
import javax.servlet.FilterChain
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse

class JwtAuthenticationTokenFilter(authenticationManager: AuthenticationManager) :
    BasicAuthenticationFilter(authenticationManager) {

    @Value("\${jwt.header}")
    lateinit var jwtHeader: String

    @Value("\${jwt.tokenHeader}")
    lateinit var jwtTokenHeader: String

    @Autowired
    lateinit var jwtTokenUtil: JwtTokenUtil

    @Autowired
    @Qualifier("userService")
    lateinit var userDetailsService: UserDetailsService

    override fun doFilterInternal(request: HttpServletRequest, response: HttpServletResponse, chain: FilterChain) {
        var authHeader: String? = request.getHeader(jwtHeader)

        if (authHeader != null && authHeader.startsWith(jwtTokenHeader)) {
            var token = authHeader.substring(jwtTokenHeader.length)
            val username = jwtTokenUtil.getUserNameFromToken(token)
            LOGGER.info("Checking user: $username")

            if (username != null && SecurityContextHolder.getContext().authentication == null) {
                var userDetails = userDetailsService.loadUserByUsername(username)
                if (jwtTokenUtil.validateToken(token, userDetails)) {
                    val authentication = UsernamePasswordAuthenticationToken(userDetails, null, userDetails.authorities)
                    SecurityContextHolder.getContext().authentication = authentication
                }
            }
        }
        chain.doFilter(request, response)
    }

    companion object {
        private val LOGGER = LoggerFactory.getLogger(JwtAuthenticationTokenFilter::class.java)
    }
}